using System;
using System.Collections;
using System.Data;
using System.Text.RegularExpressions;

using BO = PHSRAG.Insight21.BusinessObjects;
using Utility = PHSRAG.Utility;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using DataAccess = PHSRAG.Utility.DataAccess;

namespace PHSRAG.Insight21.Humans
{
	/// <summary>
	/// Represents a single submission on a protocol and its history.  The information returned by the accessors
	/// is information pertaining to the most recent IRB submission status. 
	/// </summary>
	public class Submission: BO.BusinessObject
	{
		#region Constants

		private const string SubmissionKey = "Submission_8D5FF6CE-6E67-4baf-BC69-56312E9A6825";
		private const string SubmissionTableName = "Submission";

		#endregion

		#region Instance Variables (Private)

		private ArrayList reviews;

		#endregion

		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>
		public static string CacheKey	{ get { return SubmissionKey; } }

		/// <summary>
		/// Returns current status of the submission if it exists, otherwise it returns an empty string
		/// </summary>
		public string Status
		{
			get
			{
				if (DataContainer.Tables[0].Rows.Count > 0)
					return (string)DataContainer.Tables[SubmissionTableName].Rows[0]["Status"];
				else return string.Empty;
			}
		}

		/// <summary>
		/// Indicates what number in a sequence of submissions (of the same type) this submission 
		/// is (e.g. if the submission is the second amendment on this protocol, this returns 2)
		/// </summary>
		public int SubmissionNumber
		{
			get 
			{
				string formsId = (string)DataContainer.Tables[0].Rows[0]["FormsId"];
				
				// Initial Reviews don't have a number after them
				if (formsId.IndexOf("IR") != -1)
					return 1;
				Regex regEx = new Regex(@"^\D+(?<digits>\d+)$");
				Match match = regEx.Match(formsId);
				if (match.Success)
					return Convert.ToInt32(match.Groups["digits"].Value);
				else throw new Exception("No FormsId on the Submission, Submission Number cannot be determined!");
			}
		}

		/// <summary>
		/// Returns the number of status changes this submission went through
		/// </summary>
		public int ReviewCount
		{
			get
			{
				return DataContainer.Tables[0].Rows.Count;
			}
		}
	
		/// <summary>
		/// Initialize the base class with the specified cache policy and initialize the dataContainer
		/// </summary>
		/// <param name="cachePolicy">policy to use to cache the instance</param>
		public Submission(ICachePolicy cachePolicy) : base(cachePolicy)
		{
			DataContainer = new DataSet();
		}

		#region Overrides

		/// <summary>
		/// Load the current instance with review data
		/// </summary>
		/// <param name="connectionString">Database connection string</param>
		/// <param name="args">arguments for the stored procedure</param>
		public override void Load(string connectionString, params object[] args)
		{
			if (args.Length != 1)
				throw new Exception("Submissions load requires a submission id");

			try
			{
				DataAccess.LoadDataSet(
					DataContainer,
					SubmissionTableName,
					connectionString, 
					"GetBoardReviews",
					DataAccess.BuildSqlParameterArray
					("@submissionId", SqlDbType.Int, (int)args[0]));
			}

			catch (Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Submission Load", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Submission Load failed", e);
			}
		}

		/// <summary>
		/// Adds the Submission object to the cache
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(CacheKey, this);
		}

		/// <summary>
		/// Removes the Submission object from the cache
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(CacheKey);
		}

		#endregion

		/// <summary>
		/// Iterates over its dataContainer, instantiating board review objects based on
		/// each row, and adds them to an ArrayList
		/// </summary>
		/// <returns>ArrayList containing board review objects for this submission</returns>
		public ArrayList GetBoardReviewsList()
		{
			if (reviews == null)
			{
				reviews = new ArrayList();
				DataTable dataTable = DataContainer.Tables[SubmissionTableName];

				for (int i = 0; i < dataTable.Rows.Count; ++i)
					reviews.Add(new Review(CachePolicy, dataTable.Rows[i], this));
			}
			return reviews;
		}
	}
}
